﻿namespace Summoner
{
    using UnityEngine;
    using System.IO;
    using System.Collections.Generic;
    using System;
    using System.Text;

    public class UpdateFeature
    {
        public static void TryCheckUpdate(Action callback)
        {
            GameConfigInfo LocalGameConfig = null;
            GameConfigInfo RemoteGameConfig = null;
            if (AssetPath.IsEditor)
            {
                if (callback != null)
                {
                    callback();
                }
            }
            else
            {
                if (!File.Exists(AssetPath.DocumentsPath + "/" + AssetPath.AssetConfigName.ToLower() + ".json"))
                {
#if UNITY_IOS
                    PartialLoadMgr.instance.PartialLoadMission(AssetPath.AssetConfigName, "json", ()=>
                    {
                        using (StreamReader stream = new StreamReader(AssetPath.DocumentsPath + "/" + AssetPath.AssetConfigName.ToLower() + ".json", Encoding.UTF8))
                        {
                            string text = stream.ReadToEnd();
                            RemoteGameConfig = JsonSerializer.UnpackJson<GameConfigInfo>(text);
                            stream.Close();
                            AssetManager.instance.LoadConfig(AssetPath.LoadAsyncPath + "/" + AssetPath.AssetConfigName.ToLower() + ".json", (str) =>
                            {
                                LocalGameConfig = JsonSerializer.UnpackJson<GameConfigInfo>(str);
                                CheckUpdate(LocalGameConfig, RemoteGameConfig, callback);
                            });
                        }
                    });
#else
                    PartialLoadMgr.instance.PartialLoadMission(AssetPath.AssetConfigName.ToLower(), "json", () =>
                    {
                        using (StreamReader stream = new StreamReader(AssetPath.DocumentsPath + "/" + AssetPath.AssetConfigName.ToLower() + ".json", Encoding.UTF8))
                        {
                            string text = stream.ReadToEnd();
                            RemoteGameConfig = JsonSerializer.UnpackJson<GameConfigInfo>(text);
                            stream.Close();
                            LocalGameConfig = new GameConfigInfo() { assets = new List<AssetInfo>(), version = " " };
                            CheckUpdate(LocalGameConfig, RemoteGameConfig, callback);
                        }
                    });
#endif
                }
                else
                {
                    using (StreamReader stream = new StreamReader(AssetPath.DocumentsPath + "/" + AssetPath.AssetConfigName.ToLower() + ".json", Encoding.UTF8))
                    {
                        string text = stream.ReadToEnd();
                        LocalGameConfig = JsonSerializer.UnpackJson<GameConfigInfo>(text);
                        stream.Close();
                        AssetManager.instance.LoadConfigFullpath(AssetPath.UpdatePath + "/" + AssetPath.AssetConfigName.ToLower() + ".json", (str) =>
                        {
                            RemoteGameConfig = JsonSerializer.UnpackJson<GameConfigInfo>(str);
                            CheckUpdate(LocalGameConfig, RemoteGameConfig, callback);
                        });
                    }
                }
            }
        }

        private static void CheckUpdate(GameConfigInfo LocalGameConfig, GameConfigInfo RemoteGameConfig, Action callback)
        {
            if(RemoteGameConfig.version.CompareTo(LocalGameConfig.version) == 0)
            {
                string unfinishedList = PlayerPrefs.GetString("UpdateList", "");
                if(string.IsNullOrEmpty(unfinishedList))
                {
                    if (callback != null)
                    {
                        callback();
                    }
                }
                else
                {
                    List<AssetInfo> updateList = JsonSerializer.UnpackJson<List<AssetInfo>>(unfinishedList);
                    PartialLoadMgr.instance.PartialLoadMissions(updateList, () =>
                    {
                        if (callback != null)
                        {
                            PlayerPrefs.DeleteKey("UpdateList");
                            callback();
                        }
                    });
                }
            }
            else
            {
                if (RemoteGameConfig.version.CompareTo(LocalGameConfig.version) > 0)
                {
                    Dictionary<string, AssetInfo> remote2info = new Dictionary<string, AssetInfo>();
                    Dictionary<string, AssetInfo> local2info = new Dictionary<string, AssetInfo>();
                    List<AssetInfo> updateList = new List<AssetInfo>();
                    foreach (AssetInfo info in RemoteGameConfig.assets)
                    {
                        if (!remote2info.ContainsKey(info.Name))
                        {
                            remote2info[info.Name] = info;
                        }
                    }
                    foreach (AssetInfo info in LocalGameConfig.assets)
                    {
                        if (!local2info.ContainsKey(info.Name))
                        {
                            local2info[info.Name] = info;
                        }
                    }
                    foreach (KeyValuePair<string, AssetInfo> kvp in remote2info)
                    {
                        if (!local2info.ContainsKey(kvp.Key) || local2info[kvp.Key].Md5 != kvp.Value.Md5)
                        {
                            updateList.Add(kvp.Value);
                        }
                    }
                    ReplaceFile(JsonSerializer.PackJson(RemoteGameConfig));
                    if (updateList.Count > 0)
                    {
                        updateList.Add(new AssetInfo() { assetName = "StreamingAssets" });
                        PlayerPrefs.SetString("UpdateList", JsonSerializer.PackJson(updateList));
                        PartialLoadMgr.instance.PartialLoadMissions(updateList, () =>
                        {
                            if (callback != null)
                            {
                                PlayerPrefs.DeleteKey("UpdateList");
                                callback();
                            }
                        });
                    }
                    else
                    {
                        if (callback != null)
                        {
                            callback();
                        }
                    }
                }
                else
                {
                    Debug.LogError("the local version number is wrong !");
                }
            }
        }

        private static void ReplaceFile(string content)
        {
            StringBuilder versions = new StringBuilder();
            FileStream stream = new FileStream(AssetPath.DocumentsPath + "/" + AssetPath.AssetConfigName.ToLower() + ".json", FileMode.Create);
            byte[] data = Encoding.UTF8.GetBytes(content);
            stream.Write(data, 0, data.Length);
            stream.Flush();
            stream.Close();
        }
    }
}